package com.tianhua.javs.core.factory;

import com.google.common.collect.Lists;
import com.tianhua.javs.client.bean.*;
import com.tianhua.javs.client.enums.ParamReferTypeEnum;
import com.tianhua.javs.client.model.AbstractClassModel;
import com.tianhua.javs.client.model.FieldModel;
import com.tianhua.javs.client.model.MethodModel;
import com.tianhua.javs.core.constant.TagConstants;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Description:javs 参数引用对象
 * date: 2022/2/17
 *
 * @author shenshuai
 * @version 1.0.0
 * @since JDK 1.8
 */
@Service
public class ParamReferFactory {

    /**
     * 构建业务对象bo的引用变量范围
     * @param javsVarCode
     * @param javsModelBean
     * @param javsScriptMethodBean
     * @return
     */
    public Map<String, JavsParamBean> buildBOJavsParamMap(String javsVarCode, JavsModelBean javsModelBean, JavsScriptMethodBean javsScriptMethodBean) {
        Map<String, JavsParamBean> javsParamBeanMap = new HashMap<>();
        if(javsModelBean == null){
            return javsParamBeanMap;
        }
        javsVarCode  = javsVarCode.trim();
        buildParamRefer(javsParamBeanMap,javsScriptMethodBean);

        buildFieldRefer(javsVarCode, javsModelBean.getFieldModelList(), javsParamBeanMap);
        buildMethodRefer(javsVarCode, javsModelBean.getMethodModelList(), javsParamBeanMap);

        buildClassRefer(javsVarCode, "service", javsModelBean.getServiceList(), javsParamBeanMap);
        buildClassRefer(javsVarCode, "factory", javsModelBean.getFactoryList(), javsParamBeanMap);
        buildClassRefer(javsVarCode, "repository", javsModelBean.getRepositoryList(), javsParamBeanMap);
        buildClassRefer(javsVarCode, "gataway", javsModelBean.getGatawayList(), javsParamBeanMap);
        buildConvert(javsVarCode, "convertdo" + TagConstants.BRACKET_ALL, javsModelBean.getConvertdo(), javsParamBeanMap);
        buildConvert(javsVarCode, "convertdto" + TagConstants.BRACKET_ALL, javsModelBean.getConvertdto(), javsParamBeanMap);

        return javsParamBeanMap;
    }

    /**
     * 构建业务对象dto的引用变量范围
     * @param javsVarCode
     * @param javsModelBean
     * @param javsScriptMethodBean
     * @return
     */
    public Map<String, JavsParamBean> buildDTOJavsParamMap(String javsVarCode, JavsModelBean javsModelBean,  JavsScriptMethodBean javsScriptMethodBean) {
        Map<String, JavsParamBean> javsParamBeanMap = new HashMap<>();
        if(javsModelBean == null){
            return javsParamBeanMap;
        }
        javsVarCode  = javsVarCode.trim();
        buildParamRefer(javsParamBeanMap,javsScriptMethodBean);

        buildFieldRefer(javsVarCode, javsModelBean.getFieldModelList(), javsParamBeanMap);
        buildMethodRefer(javsVarCode, javsModelBean.getMethodModelList(), javsParamBeanMap);

        //buildClassRefer(javsVarCode, "service", javsBOBean.getServiceList(), javsParamBeanMap);
        //buildClassRefer(javsVarCode, "factory", javsBOBean.getFactoryList(), javsParamBeanMap);
        buildConvert(javsVarCode, "convertbo" + TagConstants.BRACKET_ALL, javsModelBean.getConvertbo(), javsParamBeanMap);

        return javsParamBeanMap;
    }

    /**
     * 构建业务对象bo的引用变量范围
     * @param javsVarCode
     * @param javsModelBean
     * @param javsScriptMethodBean
     * @return
     */
    public Map<String, JavsParamBean> buildDOJavsParamMap(String javsVarCode, JavsModelBean javsModelBean, JavsScriptMethodBean javsScriptMethodBean) {
        Map<String, JavsParamBean> javsParamBeanMap = new HashMap<>();
        javsVarCode  = javsVarCode.trim();
        buildParamRefer(javsParamBeanMap,javsScriptMethodBean);

        buildFieldRefer(javsVarCode, javsModelBean.getFieldModelList(), javsParamBeanMap);
        buildMethodRefer(javsVarCode, javsModelBean.getMethodModelList(), javsParamBeanMap);
        buildClassRefer(javsVarCode, "mapper", Lists.newArrayList(javsModelBean.getMapper()), javsParamBeanMap);
        buildConvert(javsVarCode, "convertbo" + TagConstants.BRACKET_ALL, javsModelBean.getConvertbo(), javsParamBeanMap);

        return javsParamBeanMap;
    }

    /**
     * 构建业务对象cmd的引用变量范围
     * @param javsVarCode
     * @param javsModelBean
     * @param javsScriptMethodBean
     * @return
     */
    public Map<String, JavsParamBean> buildCMDJavsParamMap(String javsVarCode, JavsModelBean javsModelBean, JavsScriptMethodBean javsScriptMethodBean) {
        Map<String, JavsParamBean> javsParamBeanMap = new HashMap<>();
        javsVarCode  = javsVarCode.trim();
        buildParamRefer(javsParamBeanMap,javsScriptMethodBean);

        buildFieldRefer(javsVarCode, javsModelBean.getFieldModelList(), javsParamBeanMap);
        buildMethodRefer(javsVarCode, javsModelBean.getMethodModelList(), javsParamBeanMap);

        buildClassRefer(javsVarCode, "executor", Lists.newArrayList(javsModelBean.getExecutorList()), javsParamBeanMap);


        return javsParamBeanMap;
    }


    private void buildClassRefer(String javsVarCode, String classTag, List<AbstractClassModel> classList, Map<String, JavsParamBean> javsParamBeanMap) {
        for (AbstractClassModel classModel : classList) {
            String varCode;
            if (classList.size() == 1) {
                varCode = javsVarCode + TagConstants.POINT + classTag;
            } else {
                varCode = javsVarCode + TagConstants.POINT + classModel.getClassVarIdentifer();
            }
            JavsParamBean javsParamBean = JavsParamBean.ofInstance(varCode);
            javsParamBean.setReferClass(classModel);
            javsParamBean.setJavsParamReferType(ParamReferTypeEnum.CLASS_REFER.getCode());
            javsParamBeanMap.put(varCode, javsParamBean);
        }
    }


    private void buildMethodRefer(String javsVarCode, List<MethodModel> methodModelList, Map<String, JavsParamBean> javsParamBeanMap) {
        if(CollectionUtils.isEmpty(methodModelList)){
            return;
        }
        for (MethodModel methodModel : methodModelList) {
            String varCode = javsVarCode + TagConstants.POINT + methodModel.getMethdSimpleName();
            JavsParamBean javsParamBean = JavsParamBean.ofInstance(varCode);
            javsParamBean.setReferMethod(methodModel);
            javsParamBean.setJavsParamReferType(ParamReferTypeEnum.METHOD_REFER.getCode());
            javsParamBeanMap.put(varCode, javsParamBean);
        }
    }

    private void buildFieldRefer(String javsVarCode, List<FieldModel> fieldModelList, Map<String, JavsParamBean> javsParamBeanMap) {
        if(CollectionUtils.isNotEmpty(fieldModelList)){
            return;
        }
        for (FieldModel fieldModel : fieldModelList) {
            String varCode = javsVarCode + TagConstants.POINT + fieldModel.getFieldSimpleName();
            JavsParamBean javsParamBean = JavsParamBean.ofInstance(varCode);
            javsParamBean.setReferField(fieldModel);
            javsParamBean.setParamType(fieldModel.getFieldType());
            javsParamBean.setJavsParamReferType(ParamReferTypeEnum.FIELD_REFER.getCode());
            javsParamBeanMap.put(varCode, javsParamBean);
        }
    }


    /**
     * 构建转换接口
     * @param javsVarCode
     * @param classTag
     * @param convertClass
     * @param javsParamBeanMap
     */
    private void buildConvert(String javsVarCode, String classTag, AbstractClassModel convertClass, Map<String, JavsParamBean> javsParamBeanMap) {
        if(convertClass == null){
            return;
        }
        String varCode = javsVarCode + TagConstants.POINT + classTag;
        JavsParamBean javsParamBean = JavsParamBean.ofInstance(varCode);
        javsParamBean.setReferClass(convertClass);
        javsParamBean.setParamType(convertClass.getClassName());
        javsParamBean.setJavsParamReferType(ParamReferTypeEnum.CLASS_REFER.getCode());
        javsParamBeanMap.put(varCode, javsParamBean);
    }

    /**
     * 构建方法参数和运行时变量池
     * @param javsParamBeanMap
     * @param javsScriptMethodBean
     */
    private void buildParamRefer(Map<String, JavsParamBean> javsParamBeanMap, JavsScriptMethodBean javsScriptMethodBean){
        if(CollectionUtils.isNotEmpty(javsScriptMethodBean.getParamBeanList())){
            for (JavsParamBean javsParamBean : javsScriptMethodBean.getParamBeanList()){
                if(javsParamBean.getReferClass() != null){
                    javsParamBean.setParamType(javsParamBean.getReferClass().getClassName());
                }
                javsParamBeanMap.put(javsParamBean.getJavsParamName(),javsParamBean);
            }
        }

        if(CollectionUtils.isNotEmpty(javsScriptMethodBean.getRunTimeVarList())){
            for (ScriptVarMappingBean scriptVarMappingBean : javsScriptMethodBean.getRunTimeVarList()){
                JavsParamBean javsParamBean = scriptVarMappingBean.convertParamBean();
                javsParamBeanMap.put(scriptVarMappingBean.getJavsVarCode(),javsParamBean);
            }
        }
    }


}
